FrameLib  2.0
DSP processing with frames of arbitrary timing and length
FrameLib_DSP.h
Go to the documentation of this file.
1 
2 #ifndef FRAMELIB_DSP_H
3 #define FRAMELIB_DSP_H
4 
5 #include "FrameLib_Types.h"
6 #include "FrameLib_Context.h"
7 #include "FrameLib_Object.h"
9 
10 #include <algorithm>
11 #include <limits>
12 #include <memory>
13 #include <vector>
14 
25 class FrameLib_DSP : public FrameLib_Block, public FrameLib_Queueable<FrameLib_DSP>
26 {
28  using LocalQueue = FrameLib_Queueable<FrameLib_DSP>::Queue;
30 
32 
33 protected:
34 
44  {
46  : mTimeAdvance(0), mNewFrame(false), mOutputDone(false) {}
47 
48  SchedulerInfo(FrameLib_TimeFormat timeAdvance, bool newFrame, bool outputDone)
49  : mTimeAdvance(timeAdvance), mNewFrame(newFrame), mOutputDone(outputDone) {}
50 
52  bool mNewFrame;
54  };
55 
56 private:
57 
66  struct Input
67  {
68  Input() : mObject(nullptr), mIndex(0), mSize(0), mFixedInput(nullptr), mType(kFrameNormal), mUpdate(false), mParameters(false), mTrigger(true), mSwitchable(false) {}
69 
70  FrameType getCurrentType() const { return mObject ? mObject->mOutputs[mIndex].mCurrentType : kFrameNormal; }
71 
72  // Connection Info
73 
74  FrameLib_DSP *mObject;
75  unsigned long mIndex;
76 
77  // Fixed Input
78 
79  unsigned long mSize;
80  double *mFixedInput;
81 
82  // Flags
83 
84  FrameType mType;
85 
86  bool mUpdate;
87  bool mParameters;
88  bool mTrigger;
89  bool mSwitchable;
90  };
91 
99  struct Output
100  {
101  Output() : mMemory(nullptr), mType(kFrameNormal), mCurrentType(kFrameNormal), mRequestedType(kFrameNormal), mCurrentSize(0), mRequestedSize(0), mPointerOffset(0) {}
102 
103  void *mMemory;
104 
105  FrameType mType;
106  FrameType mCurrentType;
107  FrameType mRequestedType;
108 
109  size_t mCurrentSize;
110  size_t mRequestedSize;
111  size_t mPointerOffset;
112  };
113 
114 public:
115 
116  // Constructor / Destructor
117 
118  FrameLib_DSP(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans = 0);
119  ~FrameLib_DSP();
120 
121  // Non-copyable
122 
123  FrameLib_DSP(const FrameLib_DSP&) = delete;
124  FrameLib_DSP& operator=(const FrameLib_DSP&) = delete;
125 
126  // Set Fixed Inputs
127 
128  void setFixedInput(unsigned long idx, double *input, unsigned long size) final;
129  const double *getFixedInput(unsigned long idx, unsigned long *size) final;
130 
131  // Audio Processing
132 
133  void blockUpdate(const double * const *ins, double **outs, unsigned long blockSize) final;
134  void reset(double samplingRate, unsigned long maxBlockSize) final;
135 
136  // Info (individual objects should override other methods to provide info)
137 
138  const FrameLib_Parameters *getParameters() const final { return &mParameters; }
139 
140  FrameType inputType(unsigned long idx) const final { return mInputs[idx].mType; }
141  FrameType outputType(unsigned long idx) const final { return mOutputs[idx].mType; }
142 
143  // Automatic Ordering Connections
144 
145  void autoOrderingConnections() final;
146  void clearAutoOrderingConnections() final;
147 
148 protected:
149 
150  // Setup and IO Modes
151 
152  // Call these from your constructor only (unsafe elsewhere)
153 
154  void setIO(unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans = 0);
155  void setInputMode(unsigned long idx, bool update, bool trigger, bool switchable, FrameType type = kFrameNormal);
156  void setParameterInput(unsigned long idx);
157  void addParameterInput();
158  void setOutputType(unsigned long idx, FrameType type);
159 
160  // You should only call this from your process method (it is unsafe anywhere else)
161 
162  void setCurrentOutputType(unsigned long idx, FrameType type);
163 
164  // You should only call this from your update method (it is unsafe anywhere else)
165 
166  void updateTrigger(unsigned long idx, bool trigger);
167 
168  // Processing Utilities
169 
170  // Test if an Input Triggered the Current Frame
171 
172  bool isTrigger(unsigned long idx) const { return mInputs[idx].mTrigger && mInputs[idx].mObject && (mInputs[idx].mObject->mFrameTime == mFrameTime); }
173 
174  // Timing
175 
176  FrameLib_TimeFormat getFrameTime() const { return mFrameTime; }
177  FrameLib_TimeFormat getValidTime() const { return mValidTime; }
178  FrameLib_TimeFormat getInputTime() const { return mInputTime; }
179  FrameLib_TimeFormat getCurrentTime() const { return getType() == kScheduler ? mValidTime : mFrameTime; }
180  FrameLib_TimeFormat getBlockStartTime() const { return getType() == kOutput ? mBlockEndTime : mBlockStartTime; }
181  FrameLib_TimeFormat getBlockEndTime() const { return mBlockEndTime; }
182 
183  FrameLib_TimeFormat getInputFrameTime(unsigned long idx) const { return mInputs[idx].mObject ? mInputs[idx].mObject->mFrameTime : FrameLib_TimeFormat(0); }
184  FrameLib_TimeFormat getInputValidTime(unsigned long idx) const { return mInputs[idx].mObject ? mInputs[idx].mObject->mValidTime : FrameLib_TimeFormat(0); }
185 
186  // Output Allocation
187 
188  void requestOutputSize(unsigned long idx, size_t size) { mOutputs[idx].mRequestedSize = size; }
189  void requestAddedOutputSize(unsigned long idx, size_t size) { mOutputs[idx].mRequestedSize += size; }
190  bool allocateOutputs();
191 
192  // Get Inputs and Outputs
193 
194  FrameType getInputCurrentType(unsigned long idx) const { return mInputs[idx].getCurrentType(); }
195  const double *getInput(unsigned long idx, size_t *size) const;
196  const FrameLib_Parameters::Serial *getInput(unsigned long idx) const;
197 
198  FrameType getOutputCurrentType(unsigned long idx) const { return mOutputs[idx].mCurrentType; }
199  double *getOutput(unsigned long idx, size_t *size) const;
200  FrameLib_Parameters::Serial *getOutput(unsigned long idx) const;
201 
202  // Convience methods for copying and zeroing
203 
204  void prepareCopyInputToOutput(unsigned long inIdx, unsigned long outIdx);
205  void copyInputToOutput(unsigned long inIdx, unsigned long outIdx);
206 
207  static void copyVector(double *output, const double *input, unsigned long size) { std::copy(input, input + size, output); }
208  static void zeroVector(double *output, unsigned long size) { std::fill_n(output, size, 0.0); }
209 
210  static void copyVectorExtend(double* output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
211  {
212  copyVector(output, input, std::min(sizeIn, sizeOut));
213  std::fill_n(output + sizeIn, (sizeOut > sizeIn) ? sizeOut - sizeIn : 0, input[sizeIn - 1]);
214  }
215 
216  static void copyVectorWrap(double* output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
217  {
218  unsigned long excess = sizeOut % sizeIn;
219 
220  for (unsigned long i = 0; i < (sizeOut - excess); i += sizeIn)
221  copyVector(output + i, input, sizeIn);
222 
223  copyVector(output + (sizeOut - excess), input, excess);
224  }
225 
226  static void copyVectorZero(double* output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
227  {
228  copyVector(output, input, std::min(sizeIn, sizeOut));
229  zeroVector(output + sizeIn, (sizeOut > sizeIn) ? sizeOut - sizeIn : 0);
230  }
231 
232  // Convenience methods for converting time values either in time format, or double precision
233 
237 
238  double hzToSamples(double a) { return mSamplingRate / a; }
239  double msToSamples(double a) { return (a * mSamplingRate) / 1000.0; }
240  double secondsToSamples(double a) { return a * mSamplingRate; }
241 
242 private:
243 
244  // Queueable Reset
245 
246  void reset(LocalQueue *queue);
247 
248  // Customisable Processing
249 
250  // Override to handle audio at the block level
251 
252  virtual void blockProcess(const double * const *ins, double **outs, unsigned long blockSize) {}
253 
254  // Override to get called on audio reset
255 
256  virtual void objectReset() {}
257 
258  // Override for updates prior to schedule / process (e.g. adjusting triggers)
259 
260  virtual void update() {}
261 
262  // Override for scheduling code (scheduler objects must override this)
263 
264  virtual SchedulerInfo schedule(bool newFrame, bool noAdvance) = 0;
265 
266  // Override for main frame processing code (processor objects must override this)
267 
268  virtual void process() = 0;
269 
270  // Scheduling
271 
272  // This returns true if the object requires notification from an audio thread (is a scheduler/has audio input)
273 
274  bool requiresAudioNotification() { return getType() == kScheduler || getNumAudioIns(); }
275 
276  // Manage Output Memory
277 
278  inline void freeOutputMemory();
279  inline void releaseOutputMemory();
280 
281  // Dependency Notification
282 
283  inline void dependencyNotify(bool releaseMemory, bool fromInput);
284  void dependenciesReady();
285  void setOutputDependencyCount();
286  void incrementInputDependency();
287 
288  // Connections
289 
290  void connectionUpdate(Queue *queue) final;
291  void autoOrderingConnections(LocalQueue *queue);
292 
293 protected:
294 
295  // Member Variables
296 
297  // Sampling Rate and Maximum Block Size
298 
300  unsigned long mMaxBlockSize;
301 
302  // Parameters
303 
305 
306 private:
307 
308  // Processing Queue
309 
310  FrameLib_Context::ProcessingQueue mProcessingQueue;
311  FrameLib_DSP *mNext;
312 
313  // IO Info
314 
315  std::vector<FrameLib_DSP *> mInputDependencies;
316  std::vector<FrameLib_DSP *> mOutputDependencies;
317 
318  std::vector<Input> mInputs;
319  std::vector<Output> mOutputs;
320 
321  // Dependency Counts
322 
323  long mInputCount;
324  long mDependencyCount;
325  long mOutputMemoryCount;
326 
327  // Frame and Block Timings
328 
329  FrameLib_TimeFormat mFrameTime;
330  FrameLib_TimeFormat mValidTime;
331  FrameLib_TimeFormat mInputTime;
332  FrameLib_TimeFormat mBlockStartTime;
333  FrameLib_TimeFormat mBlockEndTime;
334 
335  bool mUpdatingInputs;
336  bool mNoLiveInputs;
337  bool mInUpdate;
338  bool mOutputDone;
339 };
340 
341 
355 {
356 
357 public:
358 
359  FrameLib_Processor(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns = 0, unsigned long nOuts = 0)
360  : FrameLib_DSP(kProcessor, context, proxy, info, nIns, nOuts) {}
361 
362  static ObjectType getType() { return kProcessor; }
363  static bool handlesAudio() { return false; }
364 
365 protected:
366 
367  // This prevents the user from needing to implement this method - doing so will do nothing
368 
369  virtual SchedulerInfo schedule(bool newFrame, bool noAdvance) { return SchedulerInfo(); }
370 
371  void setIO(unsigned long nIns, unsigned long nOuts) { FrameLib_DSP::setIO(nIns, nOuts); }
372 };
373 
374 
388 {
389 
390 public:
391 
392  FrameLib_AudioInput(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns = 0, unsigned long nOuts = 0, unsigned long nAudioIns = 0)
393  : FrameLib_DSP(kProcessor, context, proxy, info, nIns, nOuts, nAudioIns) {}
394 
395  static ObjectType getType() { return kProcessor; }
396  static bool handlesAudio() { return true; }
397 
398 protected:
399 
400  // This prevents the user from needing to implement this method - doing so will do nothing
401 
402  virtual SchedulerInfo schedule(bool newFrame, bool noAdvance) { return SchedulerInfo(); }
403 };
404 
405 
419 {
420 
421 public:
422 
423  FrameLib_AudioOutput(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns = 0, unsigned long nOuts = 0, unsigned long nAudioOuts = 0)
424  : FrameLib_DSP(kOutput, context, proxy, info, nIns, nOuts, nAudioOuts) {}
425 
426  static ObjectType getType() { return kOutput; }
427  static bool handlesAudio() { return true; }
428 
429 protected:
430 
431  // This prevents the user from needing to implement this method - doing so will do nothing
432 
433  virtual SchedulerInfo schedule(bool newFrame, bool noAdvance) { return SchedulerInfo(); }
434 };
435 
436 
450 {
451 
452 public:
453 
454  FrameLib_Scheduler(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns = 0, unsigned long nOuts = 0, unsigned long nAudioIns = 0)
455  : FrameLib_DSP(kScheduler, context, proxy, info, nIns, nOuts, nAudioIns) {}
456 
457  static ObjectType getType() { return kScheduler; }
458  static bool handlesAudio() { return true; }
459 
460 protected:
461 
462  // This prevents the user from needing to implement this method - doing so will do nothing
463 
464  virtual void process() {}
465 };
466 
467 #endif
ObjectType
Definition: FrameLib_Types.h:53
static bool handlesAudio()
Definition: FrameLib_DSP.h:427
FrameLib_TimeFormat msToSamples(const FrameLib_TimeFormat &a)
Definition: FrameLib_DSP.h:235
FrameType outputType(unsigned long idx) const final
Definition: FrameLib_DSP.h:141
void reset(double samplingRate, unsigned long maxBlockSize) final
Definition: FrameLib_DSP.cpp:74
Definition: FrameLib_Types.h:53
FrameType getOutputCurrentType(unsigned long idx) const
Definition: FrameLib_DSP.h:198
a set of parameters for a FrameLib object.
Definition: FrameLib_Parameters.h:30
double hzToSamples(double a)
Definition: FrameLib_DSP.h:238
bool allocateOutputs()
Definition: FrameLib_DSP.cpp:210
Definition: FrameLib_Types.h:54
a class used to represent distinct non-connectable areas in the host environment. ...
Definition: FrameLib_Context.h:21
FrameLib_TimeFormat getInputFrameTime(unsigned long idx) const
Definition: FrameLib_DSP.h:183
const double * getInput(unsigned long idx, size_t *size) const
Definition: FrameLib_DSP.cpp:270
void blockUpdate(const double *const *ins, double **outs, unsigned long blockSize) final
Definition: FrameLib_DSP.cpp:58
static void zeroVector(double *output, unsigned long size)
Definition: FrameLib_DSP.h:208
static bool handlesAudio()
Definition: FrameLib_DSP.h:363
void setParameterInput(unsigned long idx)
Definition: FrameLib_DSP.cpp:165
a set of tagged parameter values using external non-owned memory.
Definition: FrameLib_Parameters.h:51
virtual SchedulerInfo schedule(bool newFrame, bool noAdvance)
Definition: FrameLib_DSP.h:402
FrameLib_TimeFormat getBlockEndTime() const
Definition: FrameLib_DSP.h:181
FrameLib_TimeFormat getCurrentTime() const
Definition: FrameLib_DSP.h:179
an abstract class containing the core of the DSP processing system, which handles single-stream sched...
Definition: FrameLib_DSP.h:25
static bool handlesAudio()
Definition: FrameLib_DSP.h:458
FrameLib_TimeFormat mTimeAdvance
Definition: FrameLib_DSP.h:51
a virtual struct allowing for extensible communication to/from the host environment.
Definition: FrameLib_Types.h:69
void setInputMode(unsigned long idx, bool update, bool trigger, bool switchable, FrameType type=kFrameNormal)
Definition: FrameLib_DSP.cpp:155
a convenience class for creating scheduler type FrameLib_DSP classes.
Definition: FrameLib_DSP.h:449
static void copyVector(double *output, const double *input, unsigned long size)
Definition: FrameLib_DSP.h:207
a convenience class for creating processor type FrameLib_DSP classes which handle audio input...
Definition: FrameLib_DSP.h:387
static ObjectType getType()
Definition: FrameLib_DSP.h:362
a template class for items that can be placed on a queue
Definition: FrameLib_Object.h:29
const FrameLib_Parameters * getParameters() const final
Definition: FrameLib_DSP.h:138
FrameLib_TimeFormat getFrameTime() const
Definition: FrameLib_DSP.h:176
ObjectType getType() const
Definition: FrameLib_Object.h:204
FrameLib_Processor(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns=0, unsigned long nOuts=0)
Definition: FrameLib_DSP.h:359
FrameType inputType(unsigned long idx) const final
Definition: FrameLib_DSP.h:140
a struct for returning scheduling info from the schedule() method.
Definition: FrameLib_DSP.h:43
const double * getFixedInput(unsigned long idx, unsigned long *size) final
Definition: FrameLib_DSP.cpp:48
FrameLib_TimeFormat getBlockStartTime() const
Definition: FrameLib_DSP.h:180
FrameLib_AudioOutput(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns=0, unsigned long nOuts=0, unsigned long nAudioOuts=0)
Definition: FrameLib_DSP.h:423
void setCurrentOutputType(unsigned long idx, FrameType type)
Definition: FrameLib_DSP.cpp:194
FrameLib_TimeFormat getInputTime() const
Definition: FrameLib_DSP.h:178
virtual SchedulerInfo schedule(bool newFrame, bool noAdvance)
Definition: FrameLib_DSP.h:369
double mSamplingRate
Definition: FrameLib_DSP.h:299
FrameLib_DSP(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans=0)
Definition: FrameLib_DSP.cpp:6
void requestAddedOutputSize(unsigned long idx, size_t size)
Definition: FrameLib_DSP.h:189
a type for representing time in fixed-point high-precision for scheduling purposes.
Definition: FrameLib_Types.h:38
void setOutputType(unsigned long idx, FrameType type)
Definition: FrameLib_DSP.cpp:185
virtual SchedulerInfo schedule(bool newFrame, bool noAdvance)
Definition: FrameLib_DSP.h:433
FrameLib_Parameters mParameters
Definition: FrameLib_DSP.h:304
void clearAutoOrderingConnections() final
Definition: FrameLib_DSP.cpp:643
double secondsToSamples(double a)
Definition: FrameLib_DSP.h:240
FrameType getInputCurrentType(unsigned long idx) const
Definition: FrameLib_DSP.h:194
double msToSamples(double a)
Definition: FrameLib_DSP.h:239
static ObjectType getType()
Definition: FrameLib_DSP.h:395
FrameLib_Scheduler(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns=0, unsigned long nOuts=0, unsigned long nAudioIns=0)
Definition: FrameLib_DSP.h:454
a minimal processing queue that is used to non-recursively process FrameLIB_DSP objects in a network...
Definition: FrameLib_ProcessingQueue.h:30
void addParameterInput()
Definition: FrameLib_DSP.cpp:173
void requestOutputSize(unsigned long idx, size_t size)
Definition: FrameLib_DSP.h:188
SchedulerInfo()
Definition: FrameLib_DSP.h:45
void copyInputToOutput(unsigned long inIdx, unsigned long outIdx)
Definition: FrameLib_DSP.cpp:325
bool mNewFrame
Definition: FrameLib_DSP.h:52
double * getOutput(unsigned long idx, size_t *size) const
Definition: FrameLib_DSP.cpp:287
virtual void process()
Definition: FrameLib_DSP.h:464
void updateTrigger(unsigned long idx, bool trigger)
Definition: FrameLib_DSP.cpp:201
FrameLib_TimeFormat hzToSamples(const FrameLib_TimeFormat &a)
Definition: FrameLib_DSP.h:234
static ObjectType getType()
Definition: FrameLib_DSP.h:457
FrameLib_TimeFormat getInputValidTime(unsigned long idx) const
Definition: FrameLib_DSP.h:184
void prepareCopyInputToOutput(unsigned long inIdx, unsigned long outIdx)
Definition: FrameLib_DSP.cpp:309
an abstract class that represents either a single FrameLib_DSP object, or a group of connected FrameL...
Definition: FrameLib_Object.h:931
void setIO(unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans=0)
Definition: FrameLib_DSP.cpp:133
size_t blockSize(void *ptr)
Definition: FrameLib_Memory.cpp:23
a class for passing info strings to FrameLib_Parameters.
Definition: FrameLib_Parameters.h:282
a convenience class for creating processor FrameLib_DSP classes that do not handle audio...
Definition: FrameLib_DSP.h:354
SchedulerInfo(FrameLib_TimeFormat timeAdvance, bool newFrame, bool outputDone)
Definition: FrameLib_DSP.h:48
static bool handlesAudio()
Definition: FrameLib_DSP.h:396
FrameLib_TimeFormat secondsToSamples(const FrameLib_TimeFormat &a)
Definition: FrameLib_DSP.h:236
unsigned long mMaxBlockSize
Definition: FrameLib_DSP.h:300
a convenience class for creating processor type FrameLib_DSP classes which handle audio output...
Definition: FrameLib_DSP.h:418
void autoOrderingConnections() final
Definition: FrameLib_DSP.cpp:628
static ObjectType getType()
Definition: FrameLib_DSP.h:426
void setFixedInput(unsigned long idx, double *input, unsigned long size) final
Definition: FrameLib_DSP.cpp:30
FrameLib_TimeFormat getValidTime() const
Definition: FrameLib_DSP.h:177
void setIO(unsigned long nIns, unsigned long nOuts)
Definition: FrameLib_DSP.h:371
unsigned long getNumAudioIns() const
Definition: FrameLib_Object.h:218
FrameLib_DSP & operator=(const FrameLib_DSP &)=delete
Definition: FrameLib_Types.h:53
bool mOutputDone
Definition: FrameLib_DSP.h:53
FrameType
Definition: FrameLib_Types.h:54
static void copyVectorExtend(double *output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
Definition: FrameLib_DSP.h:210
ManagedPointer< FrameLib_ProcessingQueue, &Global::getProcessingQueue, &Global::releaseProcessingQueue > ProcessingQueue
Definition: FrameLib_Context.h:104
Definition: FrameLib_Types.h:53
~FrameLib_DSP()
Definition: FrameLib_DSP.cpp:16
static void copyVectorZero(double *output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
Definition: FrameLib_DSP.h:226
FrameLib_AudioInput(FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns=0, unsigned long nOuts=0, unsigned long nAudioIns=0)
Definition: FrameLib_DSP.h:392
bool isTrigger(unsigned long idx) const
Definition: FrameLib_DSP.h:172
static void copyVectorWrap(double *output, const double *input, unsigned long sizeOut, unsigned long sizeIn)
Definition: FrameLib_DSP.h:216